1 module hip.hipaudio.backend.avaudio.clip; 2 3 version(iOS): 4 public import avaudiobuffer; 5 public import avaudiotypes; 6 import objc.runtime; 7 import avaudiosinknode; 8 import hip.hipaudio.audioclip; 9 import hip.hipaudio.backend.avaudio.player; 10 import hip.api.data.audio; 11 import avaudiosourcenode; 12 import avaudioconverter; 13 14 15 extern(C) void tempDeallocator(const(AudioBufferList)* bufferList) 16 { 17 import hip.util.memory; 18 free(cast(void*)bufferList); 19 } 20 21 AudioBufferList* getAudioBufferList(AudioBuffer buff) 22 { 23 import hip.util.memory; 24 AudioBufferList* ret = cast(AudioBufferList*)malloc(AudioBufferList.sizeof); 25 ret.mNumberBuffers = 1; 26 ret.mBuffers[0] = buff; 27 return ret; 28 } 29 30 class HipAVAudioClip : HipAudioClip 31 { 32 AVAudioSourceNode source; 33 AVAudioPCMBuffer buffer; 34 AVAudioConverter converter; 35 36 this(IHipAudioDecoder decoder, HipAudioClipHint hint) 37 { 38 super(decoder, hint); //TODO: Change num channels 39 } 40 override void setBufferData(HipAudioBuffer* buffer, ubyte[] data, uint size = 0) 41 { 42 if(getHint.needsChannelConversion || getHint.needsDecode || getHint.needsResample) 43 { 44 import hip.console.log; 45 import hip.util.conv; 46 47 static void debugFormat(AVAudioFormat f) 48 { 49 import hip.console.log; 50 logln("sampleRate: ", f.sampleRate, " , interleaved: ", f.isInterleaved, " format: ", f.commonFormat ); 51 } 52 static void debugBuffer(AVAudioPCMBuffer b) 53 { 54 import hip.console.log; 55 logln("frameLength: ", b.frameLength, " , frameCapacity: ", b.frameCapacity, " stride: ", b.stride); 56 } 57 58 AVAudioFormat rawFormat = HipAVAudioPlayer.fromConfig(decoder.getAudioConfig); 59 converter = AVAudioConverter.alloc.initFromFormat( 60 rawFormat, 61 HipAVAudioPlayer.fromConfig(HipAVAudioPlayer.getAudioConfig) 62 ); 63 64 AudioBufferList* list = getAudioBufferList(AudioBuffer(decoder.getClipChannels, 65 cast(uint)getClipSize, getClipData.ptr) 66 ); 67 68 AVAudioPCMBuffer temp = AVAudioPCMBuffer.alloc.initWithPCMFormat( 69 rawFormat, list, &tempDeallocator 70 ); 71 72 73 NSError err; 74 auto convFn = block((AVAudioPacketCount inNumberOfPackets, AVAudioConverterInputStatus* outStatus) 75 { 76 if(temp.frameLength > 0) 77 { 78 *outStatus = AVAudioConverterInputStatus._HaveData; 79 return cast(AVAudioBuffer)temp; 80 } 81 else 82 { 83 *outStatus = AVAudioConverterInputStatus._NoDataNow; 84 return null; 85 } 86 }); 87 88 converter.convertToBuffer(cast(AVAudioBuffer)buffer.avaudio, &err, &convFn); 89 90 if(err) 91 { 92 import hip.error.handler; 93 ErrorHandler.assertExit(false, "Could not convert buffer: "~err.toString); 94 } 95 } 96 else 97 { 98 AVAudioFormat rawFormat = HipAVAudioPlayer.fromConfig(decoder.getAudioConfig); 99 AudioBufferList list = AudioBufferList(1, AudioBuffer(decoder.getClipChannels, 100 cast(uint)getClipSize, getClipData.ptr) 101 ); 102 this.buffer = AVAudioPCMBuffer.alloc.initWithPCMFormat( 103 rawFormat, &list, &tempDeallocator 104 ); 105 } 106 107 } 108 109 ///Nothing to do 110 override protected void onUpdateStream(ubyte[] data, uint decodedSize){} 111 112 ///Wraps an AVAudioBuffer buffer 113 override protected HipAudioBufferWrapper createBuffer(ubyte[] data) 114 { 115 this.buffer = AVAudioPCMBuffer.alloc.initWithPCMFormat(HipAVAudioPlayer.fromConfig(HipAVAudioPlayer.getAudioConfig), cast(uint)data.length); 116 HipAudioBufferWrapper ret; // TODO: implement 117 ret.buffer.avaudio = buffer; 118 return ret; 119 } 120 121 122 ///Calls XAudio2.9 specific buffer destroy 123 override protected void destroyBuffer(HipAudioBuffer* buffer) 124 { 125 126 } 127 }